package com.dbsop.domain.transport.agg;

import com.dbsop.domain.EsOrder;
import com.dbsop.domain.agg.AggOperation;
import com.dbsop.domain.agg.Group;
import com.dbsop.domain.rest.info.RFFM;
import com.dbsop.common.enums.Order;
import org.elasticsearch.search.aggregations.BucketOrder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.dbsop.common.enums.Order.DESC;

/**
 * 分组
 */
public abstract class TransportGroup extends TransportAgg implements Group {

    /**
     *  子分组
     */
    protected TransportGroup group;

    protected EsOrder esOrder;

    protected EsOrder keyOrder;

    protected int size = 500;
    /**
     *  操作聚合
     */
    protected List<AggOperation> aggOperations = new ArrayList<AggOperation>();

    public TransportGroup(String fieldName) {
        super(fieldName);
    }

    public TransportGroup(String fieldName, String formatName) {
        super(fieldName, formatName);
    }



    protected   List<BucketOrder> order(){
        if (esOrder == null) return null;
        List<BucketOrder> bucketOrders = new ArrayList<>();
        boolean order = esOrder.getOrder()==DESC?false:true;
        for (String field : esOrder.getFields()) {
            bucketOrders.add(BucketOrder.aggregation(field,order));
        }
        return bucketOrders;
    }

    protected  BucketOrder keyOrder(){
        if (keyOrder == null){
            return null;
        }
        boolean order = keyOrder.getOrder()==DESC?false:true;
        return BucketOrder.key(order);
    }

    public TransportGroup getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = (TransportGroup) group;
    }

    public List<AggOperation> getAggOperations() {
        return aggOperations;
    }

    public void add(AggOperation aggOperation){
        aggOperations.add(aggOperation);
    }

    public int getSize() {
        return size;
    }



    public TransportGroup groupSub(String fieldName){
        group =  new TransportTermGroup(fieldName);
        return group;
    }

    public TransportGroup groupSub(String fieldName, String formatName){
        group =  new TransportTermGroup(fieldName,formatName);
        return group;
    }


    public TransportGroup rangeSub(String fieldName, RFFM ... rffms){
        TransportScopeGroup scopeGroup = new TransportScopeGroup(fieldName);
        for (RFFM rffm : rffms) {
            scopeGroup.add(rffm);
        }
        group =  scopeGroup;
        return group;
    }

    public TransportGroup rangeSub(String fieldName, String formatName, RFFM ... rffms){
        TransportScopeGroup scopeGroup = new TransportScopeGroup(fieldName,formatName);
        for (RFFM rffm : rffms) {
            scopeGroup.add(rffm);
        }
        group =  scopeGroup;
        return group;
    }


    public TransportGroup sum(String fieldName){
        add(new TransportSum(fieldName));
        return this;
    }

    public TransportGroup avg(String fieldName){
        add(new TransportAvg(fieldName));
        return this;
    }
    public TransportGroup count(String fieldName){
        add(new TransportCount(fieldName));
        return this;
    }

    public TransportGroup max(String fieldName){
        add( new TransportMax(fieldName));
        return this;
    }

    public TransportGroup maxExtFields(String fieldName, String... fields){
        maxExtFields(fieldName,1,fields);
        return this;
    }

    public TransportGroup maxExtFields(String fieldName, int num, String... fields){
        TopHits topHits = new TopHits(fieldName, Order.DESC,num);
        if (fields!=null){
            for (String field: fields) {
                topHits.addField(field);
            }
        }
        topHits.addField(fieldName);
        add(topHits);
        return this;
    }

    public TransportGroup min(String fieldName){
        add( new TransportMin(fieldName));
        return this;
    }

    public TransportGroup minExtFields(String fieldName, String... fields){
        minExtFields(fieldName,1,fields);
        return this;
    }

    public TransportGroup minExtFields(String fieldName, int num, String... fields){
        TopHits topHits = new TopHits(fieldName, Order.ASC,num);
        if (fields!=null){
            for (String field: fields) {
                topHits.addField(field);
            }
        }
        topHits.addField(fieldName);
        add(topHits);
        return this;
    }

    public TransportGroup sum(String fieldName, String formatName){
        add(new TransportSum(fieldName,formatName));
        return this;
    }

    public TransportGroup avg(String fieldName, String formatName){
        add(new TransportAvg(fieldName,formatName));
        return this;
    }
    public TransportGroup count(String fieldName, String formatName){
        add(new TransportCount(fieldName,formatName));
        return this;
    }

    public TransportGroup max(String fieldName, String formatName){
        add(new TransportMax(fieldName,formatName));
        return this;
    }
    public TransportGroup min(String fieldName, String formatName){
        add(new TransportMin(fieldName,formatName));
        return this;
    }

    public TransportGroup size(int size){
        this.size = size;
        return this;
    }

    public TransportGroup order(Order order, String ...fieldNames){
        if (fieldNames == null)return this;
        esOrder = new EsOrder( Arrays.stream(fieldNames).collect(Collectors.toList()),order);
        return this;
    }

    public TransportGroup orderKey(Order order){
        this.keyOrder = new EsOrder(order);
        return this;
    }


    public void cleanAgg(){
        aggOperations.clear();
    }
}
